package com.ruiysoft.service.order.aop;

import com.alibaba.fastjson.JSON;
import com.ruiysoft.controller.aftersaleconf.InnrAftersaleConfApi;
import com.ruiysoft.controller.aftersaleconf.vo.AftersaleConfVo;
import com.ruiysoft.entity.order.OrderDetail;
import com.ruiysoft.entity.order.OrderMain;
import com.ruiysoft.entity.order.OrderOperateRecord;
import com.ruiysoft.pub.core.Result;
import com.ruiysoft.service.order.IOrderMQAfterOperate;
import com.ruiysoft.service.order.IOrderOperateRecordService;
import com.ruiysoft.service.order.anno.OrderOperate;
import com.ruiysoft.service.order.bean.OrderPaymentCallbackDto;
import com.ruiysoft.service.order.consts.OrderOperateTypeEnum;
import com.ruiysoft.service.order.facade.OrderPubFacade;
import com.ruiysoft.service.order.mq.bean.OrderMQAfterOperateBean;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Date : 2019/1/5
 *
 * @author WenJialu
 */
@Aspect
@Component
public class OrderOperateAspect {
	private static Logger logger = LoggerFactory.getLogger(OrderOperateAspect.class);
	private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();

	@Resource
	private IOrderOperateRecordService orderOperateRecordService;
	@Resource
	private OrderPubFacade orderPubFacade;
	@Resource
	IOrderMQAfterOperate orderMQAfterOperate;
	@Autowired
	InnrAftersaleConfApi innrAftersaleConfApi;


	@Pointcut("@annotation(com.ruiysoft.service.order.anno.OrderOperate)")
	public void pointCut(){}

	@AfterReturning(returning = "result", pointcut = "pointCut()")
	@Order(2)
	public void afterOrderOperate(JoinPoint point, Object result){
		MethodSignature signature = (MethodSignature) point.getSignature();

		//方法参数列表
		String[] paramNames = signature.getParameterNames();
		Object[] args = point.getArgs();

		//获取注解信息
		OrderOperate anno = signature.getMethod().getAnnotation(OrderOperate.class);
		String orderNoEl = anno.orderNo();
		String operatorIdEl = anno.operatorId();
		OrderOperateTypeEnum operateType = anno.operateType();
		String returningContextKey = anno.returningContextKey();

		//上下文
		EvaluationContext context = new StandardEvaluationContext();
		logger.info("Method Parameters -->  \n");
		for (int i = 0; i < paramNames.length; i++) {
			context.setVariable(paramNames[i], args[i]);
			logger.info(paramNames[i] + " --> " + args[i]);
		}
		Optional.ofNullable(result).ifPresent(v -> context.setVariable(returningContextKey, v));

		//获取订单号及操作者userId
		String orderNo = EXPRESSION_PARSER.parseExpression(orderNoEl.startsWith("#") ? orderNoEl : "#" + orderNoEl).getValue(context, String.class);
		//Long operatorId = EXPRESSION_PARSER.parseExpression(operatorIdEl.startsWith("#") ? operatorIdEl : "#" + operatorIdEl).getValue(context, Long.class);
		Long operatorId = operatorIdEl.startsWith("#")
				? EXPRESSION_PARSER.parseExpression(operatorIdEl).getValue(context, Long.class)
				: (NumberUtils.isNumber(operatorIdEl)
					? Long.valueOf(operatorIdEl)
					: EXPRESSION_PARSER.parseExpression("#" + operatorIdEl).getValue(context, Long.class));

		//send mq
		OrderMQAfterOperateBean orderAfterOper = handleOrderMQAfterOperateBean(orderNo, operateType, result);
		if(logger.isInfoEnabled()) {
			logger.info("handleOrderMQAfterOperateBean:{}",JSON.toJSONString(orderAfterOper));
		}
		if(orderAfterOper.isOperateSuccess()) {
			//如果当前步骤成功，则推送MQ
			orderMQAfterOperate.send(orderAfterOper);
		}
		//insert record
		orderOperateRecordService.save(new OrderOperateRecord()
				                                 .setOrderNo(orderNo)
				                                 .setOperateType(operateType.getCode())
				                                 .setOperatorId(operatorId)
				                                 .setCreateTime(new Date()));

	}

	private OrderMQAfterOperateBean handleOrderMQAfterOperateBean(String orderNo, OrderOperateTypeEnum operateType, Object methodResult) {
		//ordermain
		OrderMain orderMain = null;
		OrderMQAfterOperateBean orderAfterOper = new OrderMQAfterOperateBean();//默认 operateSuccess == false,不推mq。
		orderAfterOper.setOperateType(operateType).setOrderNo(orderNo);
		//switch
		switch (operateType) {
			case ORDER_CREATE:
				break;
			case GET_GENERATE_PAY_TRANSACTION:
				break;
			case CUSTOMER_PAID:
				//fixme 改为前端支付（目前是后端回调，缺失前端付款调用过程）
				//fixme 缺少状态的话，在进行排错的时候，可能会增加难度
				orderMain = orderPubFacade.getOrderMain(Objects.requireNonNull(orderNo, "订单号为空"));
				OrderPaymentCallbackDto dto = (OrderPaymentCallbackDto) methodResult;
				orderAfterOper.setOperateSuccess(dto.isSuccess());
				break;
			case PLATFORM_CONFIRMED_PAID:
				//fixme 后端回调
				//fixme 把上面的代码移植到此
				break;
			case SHOP_CONFIRMED_PAID:
			case DELIVER:
			case RECEIVE_CONFIRM:
				//设置为 SYSTEM_SIGN，进入 SYSTEM_SIGN 消息通知流程
                orderAfterOper.setOperateType(OrderOperateTypeEnum.SYSTEM_SIGN);
			case SYSTEM_SIGN:
				Result<OrderMain> result = (Result<OrderMain>)methodResult;
				if(result.isSuccess()) {
					orderMain = result.getData();
					List<OrderDetail> details = orderPubFacade.getOrderDetails(orderNo);
					List<Long> skuIds = details.stream().map(od -> od.getSkuId()).collect(Collectors.toList());
					Result<Map<Long, AftersaleConfVo>> rac = innrAftersaleConfApi.innrAftersaleConfGetConfPost(skuIds);
					Integer max = Integer.valueOf(0);
					/*if(rac.isSuccess()){*/
					for (AftersaleConfVo acv : rac.getData().values()) {
						if (acv.getReturnedDay().compareTo(max) > 0) {
							max = acv.getReturnedDay();
						}
					}
					orderAfterOper.setFinalSignTime(orderMain.getFinalSignTime());
					orderAfterOper.setCashWithdrawableTime(DateUtils.addDays(orderMain.getFinalSignTime(), max));
					orderAfterOper.setOperateSuccess(true);
					logger.debug("setFinalSignTime:{},max:{},AftersaleConfVo is success:{}",orderMain.getFinalSignTime(),max,rac.isSuccess());
					/*} else {
						//TODO error 处理（也可能没有错误）
					}*/
				} else {
					//系统签收失败，不发任何信息
					orderAfterOper.setOperateSuccess(false);
				}
				break;
			case BARTER:
			case BARTER_SHOP_CONFIRM:
			case RETURNED_PURCHASE:
			case RETURNED_PURCHASE_CONFIRM:
			case SHOP_REFUND:
			case ORDER_CANCELL:
			case ORDER_CLOSE:
			case ORDER_OVER:
			default:
		}
		if(orderMain != null && orderAfterOper.isOperateSuccess()) {
			orderAfterOper
					.setPayAmount(orderMain.getCollectedAmount())
					.setPaidTime(orderMain.getPayTime())
					.setFreight(orderMain.getFreight())
					.setShopId(orderMain.getShopId())
					.setUserId(orderMain.getUserId())
					.setCustomerOpenId(orderMain.getOpenId());
		}

		return orderAfterOper;
	}
}
